package com.mjk.common.util;


import com.mjk.common.tools.logger.BizLogger;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;

public class NumberUtils {

	static Random random = new Random();
	public static Float discountFee(Float real_fee, Float discont) {
		String realFeeStr = real_fee.toString();
		BigDecimal realFee = new BigDecimal(realFeeStr);
		BigDecimal substractor = new BigDecimal(realFeeStr)
				.multiply(new BigDecimal("100").subtract(
						new BigDecimal(discont.toString())).divide(
						new BigDecimal("100")));

		BigDecimal substractor2 = substractor.setScale(2,
                RoundingMode.CEILING);
		BizLogger.info("手续费:" + substractor + "->转换后手续费："
				+ substractor2);
		BigDecimal discountFee = realFee.subtract(substractor2);

		return discountFee.floatValue();
	}

	public static Float discountFee2(Float real_fee, Float discount) {
		String realFeeStr = real_fee.toString();
		BigDecimal realFee = new BigDecimal(realFeeStr);
		BigDecimal substractor = new BigDecimal(discount.toString());

		BigDecimal substractor2 = substractor.setScale(2,
                RoundingMode.CEILING);
		BizLogger.info("手续费:" + substractor + "->转换后手续费："
				+ substractor2);
		BigDecimal discountFee = realFee.add(substractor2);

		return discountFee.floatValue();
	}

	/**
	 * 获取Integer对象的数值
	 * 
	 * @param value
	 *            Integer对象
	 * @return value不为空返回value，否则返回0
	 */
	public static Integer valueOf(Integer value) {
		return value != null ? value : 0;
	}

	/**
	 * 获取Long对象的数值
	 * 
	 * @param value
	 *            Long对象
	 * @return value不为空返回value，否则返回0
	 */
	public static Long valueOf(Long value) {
		return value != null ? value : 0L;
	}

	/**
	 * 获取Double对象的数值
	 * 
	 * @param value
	 *            Double对象
	 * @return value不为空返回value，否则返回0
	 */
	public static Double valueOf(Double value) {
		return value != null ? value : 0L;
	}

	/**
	 * 获取Float对象的数值
	 * 
	 * @param value
	 *            Float对象
	 * @return value不为空返回value，否则返回0
	 */
	public static Float valueOf(Float value) {
		return value != null ? value : 0L;
	}

	/**
	 * 将字符串转换为Integer类型对象
	 * 
	 * @param str
	 *            数字字符串
	 * @return 成功返回字符串对应的Integer对象，失败返回null
	 */
	public static Integer intValue(String str) {
		if (ObjectUtils.isNotEmpty(str)) {
			try {
				return Integer.parseInt(str);
			} catch (NumberFormatException e) {
				BizLogger.info(e);
			}
		}
		return null;
	}
	public static Integer intValue(char str) {
		if (ObjectUtils.isNotEmpty(str)) {
			try {
				return (int) str;
			} catch (NumberFormatException e) {
				BizLogger.info(e);
			}
		}
		return null;
	}

	/**
	 * 将字符串转换为Long类型对象
	 * 
	 * @param str
	 *            数字字符串
	 * @return 成功返回字符串对应的Long对象，失败返回null
	 */
	public static Long longValue(String str) {
		if (ObjectUtils.isNotEmpty(str)) {
			try {
				return Long.parseLong(str);
			} catch (NumberFormatException e) {
				BizLogger.info(e);
			}
		}
		return null;
	}

	/**
	 * 将字符串转换为Double类型对象
	 * 
	 * @param str
	 *            数字字符串
	 * @return 成功返回字符串对应的Double对象，失败返回null
	 */
	public static Double doubleValue(String str) {
		if (ObjectUtils.isNotEmpty(str)) {
			try {
				return Double.parseDouble(str);
			} catch (NumberFormatException e) {
				BizLogger.info(e);
			}
		}
		return null;
	}

	/**
	 * 将字符串转换为Float类型对象
	 * 
	 * @param str
	 *            数字字符串
	 * @return 成功返回字符串对应的Float对象，失败返回null
	 */
	public static Float floatValue(String str) {
		if (ObjectUtils.isNotEmpty(str)) {
			try {
				return Float.parseFloat(str);
			} catch (NumberFormatException e) {
				BizLogger.info(e);
			}
		}
		return null;
	}

	/**
	 * 判断两个数字是否相等
	 * 
	 * @param value1
	 *            Integer对象1
	 * @param value2
	 *            Integer对象2
	 * @return 相等返回true，否则返回false
	 */
	public static boolean isEqual(Integer value1, Integer value2) {
		if (value1 != null && value2 != null) {
			return value1.equals(value2);
		}
		return false;
	}

	public static boolean notEqual(Integer value1, Integer value2) {
		return !isEqual(value1, value2);
	}

	/**
	 * 判断两个数字是否相等
	 * 
	 * @param value1
	 *            Long对象1
	 * @param value2
	 *            Long对象2
	 * @return 相等返回true，否则返回false
	 */
	public static boolean isEqual(Long value1, Long value2) {
		if (value1 != null && value2 != null) {
			return value1.equals(value2);
		}
		return false;
	}

	public static boolean notEqual(Long value1, Long value2) {
		return !isEqual(value1, value2);
	}

	/**
	 * 判断两个数字是否相等
	 * 
	 * @param value1
	 *            Double对象1
	 * @param value2
	 *            Double对象2
	 * @return 相等返回true，否则返回false
	 */
	public static boolean isEqual(Double value1, Double value2) {
		if (value1 != null && value2 != null) {
			return value1.equals(value2);
		}
		return false;
	}

	public static boolean notEqual(Double value1, Double value2) {
		return !isEqual(value1, value2);
	}

	/**
	 * 获取min到max的一个随机整数x，x>=min && x<=max
	 * 
	 * @param min
	 *            随机数最小值
	 * @param max
	 *            随机数最大值
	 * @return 随机整数
	 */
	public static int random(int min, int max) {

		return ((max - min + 1) * random.nextInt()) + min;
	}

	public static double random(double min, double max) {
		return (max - min) * Math.random() + min;
	}

	public static long random(long min, long max) {
		return ((max - min + 1) * random.nextLong()) + min;
	}

	public static Integer parseInt(String s) {
		if (s != null && !s.isEmpty()) {
			try {
				return Integer.parseInt(s);
			} catch (Exception e) {
				BizLogger.info(e);
			}
		}
		return null;
	}

	public static Long parseLong(String s) {
		if (s != null && !s.isEmpty()) {
			try {
				return Long.parseLong(s);
			} catch (Exception e) {
				BizLogger.info(e);
			}
		}
		return null;
	}

	public static Double parseDouble(String s) {
		if (s != null && !s.isEmpty()) {
			try {
				return Double.parseDouble(s);
			} catch (Exception e) {
				BizLogger.error(e);
			}
		}
		return null;
	}

	public static Float parseFloat(String s) {
		if (s != null && !s.isEmpty()) {
			try {
				return Float.parseFloat(s);
			} catch (Exception e) {
				BizLogger.error(e);
			}
		}
		return null;
	}

	public static List<Integer> getRandomIndexList(int size, int indexCount) {
		List<Integer> indexList = new LinkedList<>();
		List<Integer> allIndexList = new LinkedList<>();
		for (int i = 0; i < size; i++) {
			allIndexList.add(i);
		}

		for (int i = 0; i < indexCount; i++) {
			int allIndexSize = allIndexList.size();
			if (allIndexSize == 0) {
				break;
			}
			indexList.add(allIndexList.remove(random(0, allIndexSize - 1)));
		}
		return indexList;
	}

	public static String formatAmount(Double amount, int decimalCount) {
		if (amount == null)
			amount = 0d;
		return String.format("%." + decimalCount + "f", amount);
	}

	public static String formatAmount(Float amount, int decimalCount) {
		if (amount == null)
			amount = 0f;
		return String.format("%." + decimalCount + "f", amount);
	}

	/**
	 * 由于Java的简单类型不能够精确的对浮点数进行运算，这个工具类提供精 确的浮点数运算，包括加减乘除和四舍五入。
	 */

	// 默认除法运算精度
	private static final int DEF_DIV_SCALE = 10;

	/**
	 * 提供精确的加法运算。
	 * 
	 * @param value1
	 *            被加数
	 * @param value2
	 *            加数
	 * @return 两个参数的和
	 */
	public static double add(double value1, double value2) {
		BigDecimal b1 = new BigDecimal(Double.toString(value1));
		BigDecimal b2 = new BigDecimal(Double.toString(value2));
		return b1.add(b2).doubleValue();
	}

	/**
	 * 提供精确的加法运算。
	 * 
	 * @param values
	 *            加数
	 * @return 所有参数的和
	 */
	public static double addAll(double... values) {
		double total = 0;
        for (double value : values) {
            total = add(total, value);
        }
        return total;
	}

	/**
	 * 提供精确的减法运算。
	 * 
	 * @param value1
	 *            被减数
	 * @param value2
	 *            减数
	 * @return 两个参数的差
	 */

	public static double subtract(double value1, double value2) {
		BigDecimal b1 = new BigDecimal(Double.toString(value1));
		BigDecimal b2 = new BigDecimal(Double.toString(value2));
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 提供精确的乘法运算。
	 * 
	 * @param value1
	 *            被乘数
	 * @param value2
	 *            乘数
	 * @return 两个参数的积
	 */

	public static double multiply(double value1, double value2) {
		BigDecimal b1 = new BigDecimal(Double.toString(value1));
		BigDecimal b2 = new BigDecimal(Double.toString(value2));
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 提供精确的乘法运算。由scale参数指 定精度，对结果四舍五入
	 * 
	 * @param value1
	 *            被乘数
	 * @param value2
	 *            乘数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的积
	 */

	public static double multiply(double value1, double value2, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b1 = new BigDecimal(Double.toString(value1));
		BigDecimal b2 = new BigDecimal(Double.toString(value2));
		return round(b1.multiply(b2).doubleValue(), scale);
	}

	/**
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
	 * 
	 * @param value1
	 *            被除数
	 * @param value2
	 *            除数
	 * @return 两个参数的商
	 */

	public static double divide(double value1, double value2) {
		return divide(value1, value2, DEF_DIV_SCALE);
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 * 
	 * @param value1
	 *            被除数
	 * @param value2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */

	public static double divide(double value1, double value2, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b1 = new BigDecimal(Double.toString(value1));
		BigDecimal b2 = new BigDecimal(Double.toString(value2));
		return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
	}

	/**
	 * 提供精确的小数位四舍五入处理。
	 * 
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */

	public static Double round(Double v, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
	}

	/**
	 * 提供精确的小数位一直入处理。
	 * 
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 一直入处理的结果
	 */

	public static Double roundUp(Double v, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, RoundingMode.UP).doubleValue();
	}

	/**
	 * 提供精确的小数位一直舍处理。
	 * 
	 * @param scale
	 *            小数点后保留几位
	 * @return 一直舍的结果
	 */

	public static Double roundDown(Double v, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, RoundingMode.DOWN).doubleValue();
	}

	/**
	 * 提供精确的加法运算。
	 * 
	 * @param value1
	 *            被加数
	 * @param value2
	 *            加数
	 * @return 两个参数的和
	 */
	public static float add(float value1, float value2) {
		BigDecimal b1 = new BigDecimal(Float.toString(value1));
		BigDecimal b2 = new BigDecimal(Float.toString(value2));
		return b1.add(b2).floatValue();
	}

	/**
	 * 提供精确的减法运算。
	 * 
	 * @param value1
	 *            被减数
	 * @param value2
	 *            减数
	 * @return 两个参数的差
	 */

	public static float subtract(float value1, float value2) {
		BigDecimal b1 = new BigDecimal(Float.toString(value1));
		BigDecimal b2 = new BigDecimal(Float.toString(value2));
		return b1.subtract(b2).floatValue();
	}

	/**
	 * 提供精确的乘法运算。
	 * 
	 * @param value1
	 *            被乘数
	 * @param value2
	 *            乘数
	 * @return 两个参数的积
	 */

	public static float multiply(float value1, float value2) {
		BigDecimal b1 = new BigDecimal(Float.toString(value1));
		BigDecimal b2 = new BigDecimal(Float.toString(value2));
		return b1.multiply(b2).floatValue();
	}

	/**
	 * 提供精确的乘法运算。由scale参数指 定精度，对结果四舍五入
	 * 
	 * @param value1
	 *            被乘数
	 * @param value2
	 *            乘数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的积
	 */

	public static float multiply(float value1, float value2, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b1 = new BigDecimal(Float.toString(value1));
		BigDecimal b2 = new BigDecimal(Float.toString(value2));
		return round(b1.multiply(b2).floatValue(), scale);
	}

	/**
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
	 * 
	 * @param value1
	 *            被除数
	 * @param value2
	 *            除数
	 * @return 两个参数的商
	 */

	public static float divide(float value1, float value2) {
		return divide(value1, value2, DEF_DIV_SCALE);
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 * 
	 * @param value1
	 *            被除数
	 * @param value2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */

	public static float divide(float value1, float value2, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b1 = new BigDecimal(Float.toString(value1));
		BigDecimal b2 = new BigDecimal(Float.toString(value2));
		return b1.divide(b2, scale, RoundingMode.HALF_UP).floatValue();
	}

	/**
	 * 判断传入的字符串是否全是数字
	 * 
	 * @return boolean
	 */
	public static boolean isDigit(String str) {
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		return pattern.matcher(str).matches();
	}

	/**
	 * 提供精确的小数位四舍五入处理。
	 * 
	 * @param value
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */

	public static Float round(Float value, int scale) {
		if (scale < 0) {
			BizLogger.info(new IllegalArgumentException(
					"The scale must be a positive integer or zero"));
		}
		BigDecimal b = new BigDecimal(Float.toString(value));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, RoundingMode.HALF_UP).floatValue();
	}
	public static long toLong(String str, long defaultValue) {
        if (str == null) {
            return defaultValue;
        }
        try {
            return Long.parseLong(str);
        } catch (NumberFormatException nfe) {
            return defaultValue;
        }
    }
	
	public static String hexAdd(String hex, int num){
		hex = hex.toLowerCase();
		char[] hexs = "0123456789abcdef".toCharArray();
		int len = hex.length()-1;
		//是否需要进位
		boolean b = true;
		//参与了运算的位，运算之后的结果字符串，
		//由右向左运算，首先是最后一位参与运算，如果需要进位，那么倒数第二位也要参与运算。以些类推
		//String change;
		//最终运算结果，由未参与运算的位和参与了运算的位两部分组成
		String result = "";
        StringBuilder changeBuilder = new StringBuilder();
        while(b && len>=0){
			char c = hex.charAt(len);
			int index = indexOfCharArray(hexs, c);
			if(index == -1){
				return "所传的字符串参数非法！";
			}else{
				int sum = index+num;
				if(sum<16){
					changeBuilder.insert(0, hexs[sum]);
					result = hex.substring(0, len)+ changeBuilder;
					b = false;
				}else{
					changeBuilder.insert(0, hexs[sum % 16]);
					num = sum/16;
				}
			}
			--len;
		}
		StringBuilder change = changeBuilder;
        while(b){
			if(num<16){
				change.insert(0,hexs[num]);
//				change = hexs[num]+change;
				result = change.toString();
				b= false;
			}else{
				change.insert(0,hexs[num%16]);
				//change = hexs[num%16]+change;
				num /= 16;
			}
		}
		return result.toUpperCase();
	}
	/**
	 * 获取字符在字符数组中的下标
	 * 参数一：字符数组
	 * 参数二：字符
	 * 返回值：字符在字符数组中的下标，如果字符数组中没有该字符，返回-1
	 */
	public static int indexOfCharArray(char[] charArray, char c){
		for(int i=0, len=charArray.length; i<len; ++i){
			if(charArray[i]==c){
				return i;
			}
		}
		return -1;
	}
	

}